package com.zmj.sy.mom.srv.aps.utils.nest;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zmj.sy.mom.srv.aps.bean.dto.feign.Ltk.LtkPushTokenDto;
import com.zmj.sy.mom.srv.aps.bean.entity.base.BaseEntity;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.Plate;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.PlatePhase;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.WmsPlatePick;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.WorkDetailTask;
import com.zmj.sy.mom.srv.aps.bean.entity.nest.NestSpace;
import com.zmj.sy.mom.srv.aps.bean.entity.nest.NestSpacePart;
import com.zmj.sy.mom.srv.aps.bean.entity.nest.NestSpacePlate;
import com.zmj.sy.mom.srv.aps.bean.entity.order.*;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.DictData;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.DictType;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.Factory;
import com.zmj.sy.mom.srv.aps.bean.entity.third.*;
import com.zmj.sy.mom.srv.aps.bean.vo.base.Result;
import com.zmj.sy.mom.srv.aps.bean.vo.lantek.*;
import com.zmj.sy.mom.srv.aps.bean.vo.nest.*;
import com.zmj.sy.mom.srv.aps.bean.vo.nest.workspace.WorkSpaceCreateReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.nestpre.LantekPreDrawInfoVo;
import com.zmj.sy.mom.srv.aps.bean.vo.nestpre.LantekPreDrawReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.plate.PlateListReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.plate.PlateListResVo;
import com.zmj.sy.mom.srv.aps.feign.ApsWmsApiClient;
import com.zmj.sy.mom.srv.aps.feign.LantekProApiClient;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.*;
import feign.Request;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Slf4j
@Component
public class LantekNestRule extends DefaultNestRule {

    private final ObjectMapper objectMapper;

    private final OrderPartMapper orderPartMapper;

    private final FactoryMapper factoryMapper;

    private final SinoCamPushDrawingMapper sinoCamPushDrawingMapper;

    private final LantekProApiClient lantekProApiClient;
    private final ApsOrderMapper apsOrderMapper;
    private final ApsWorkOrderMapper apsWorkOrderMapper;
    private final OrderBomMapper orderBomMapper;
    private final OrderMapper orderMapper;
    private final SinoCamPushPlanMapper sinoCamPushPlanMapper;
    private final NestSpacePartMapper nestSpacePartMapper;
    private final NestSpaceMapper nestSpaceMapper;
    private final ApsWmsApiClient apsWmsApiClient;
    private final NestSpacePlateMapper nestSpacePlateMapper;
    private final SinoCamReceiveNestNestMapper sinoCamReceiveNestNestMapper;
    private final SinoCamReceiveNestPartMapper sinoCamReceiveNestPartMapper;
    private final SinoCamReceiveNestPlateMapper sinoCamReceiveNestPlateMapper;
    private final SinoCamReceiveNestExcessMapper sinoCamReceiveNestExcessMapper;
    private final SinoCamReceiveNestMoveMapper sinoCamReceiveNestMoveMapper;
    private final ApsWorkDetailMapper apsWorkDetailMapper;
    private final PlateMapper plateMapper;
    private final PlatePhaseMapper platePhaseMapper;
    private final WmsPlatePickMapper wmsPlatePickMapper;
    private final WorkDetailTaskMapper workDetailTaskMapper;
    private final DictTypeMapper dictTypeMapper;
    private final DictDataMapper dictDataMapper;

    @Value("${project.feign.dxf-download}")
    private String dxfDownload;

    @Override
    public String getCode() {
        return NestRule.LANTEK;
    }

    @Override
    public boolean isPre() {
        return getCode().split(":")[1].equals("1");
    }

    @Override
    public String getSource() {
        return getCode().split(":")[0];
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void partAdd(List<OrderBom> orderBomList) {

        Collection<OrderBom> values = orderBomList.stream().collect(Collectors.toMap(e -> e.getPlmId(), Function.identity(), (e1, e2) -> e1)).values();

        List<SinoCamPushDrawing> sinoCamPushDrawList = sinoCamPushDrawingMapper.lambdaQuery()
                .in(SinoCamPushDrawing::getPartId, orderBomList.stream().map(OrderBom::getPlmId).collect(Collectors.toList()))
                .list();
        Map<String, List<SinoCamPushDrawing>> sinoCamPushDrawMap = sinoCamPushDrawList.stream().collect(Collectors.groupingBy(SinoCamPushDrawing::getPartId));

        List<OrderPart> orderPartList = orderPartMapper.lambdaQuery()
                .in(OrderPart::getPlmId, orderBomList.stream().map(OrderBom::getPlmId).collect(Collectors.toList()))
                .list();
        Map<String, List<OrderPart>> orderPartMap = orderPartList.stream().collect(Collectors.groupingBy(OrderPart::getPlmId));

        // 获取工厂信息
        List<Factory> factoryList = factoryMapper.selectList(null);
        Map<Integer, Factory> factoryMap = factoryList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<SinoCamPushDrawing> sinoCamPushDraws = new ArrayList<>();

        for (OrderBom orderBom : values) {
            List<SinoCamPushDrawing> sinoCamPushDrawsPart = sinoCamPushDrawMap.get(orderBom.getPlmId());
            if (CollUtil.isNotEmpty(sinoCamPushDrawsPart)) {
                continue;
            }

            List<OrderPart> orderParts = orderPartMap.get(orderBom.getPlmId());

            String standard = orderBom.getStandards();
            String[] split = standard.split("δ");

            String factoryIdk = factoryMap.get(orderBom.getFactoryId()).getMyCode();

            SinoCamPushDrawing pushDraw = new SinoCamPushDrawing();
            pushDraw.setFactoryIdk(factoryIdk);
            pushDraw.setNorm(orderBom.getStandards());
            pushDraw.setPartId(orderBom.getPlmId());
            pushDraw.setPartName(orderBom.getMaterName());
            pushDraw.setPartType(1);
            pushDraw.setPushType(2);
            pushDraw.setVersionNum(1L);
            if (StringUtils.hasText(orderBom.getTexture())) {
                pushDraw.setTexture(orderBom.getTexture());
            } else {
                pushDraw.setTexture(split[0]);
            }
            if (orderBom.getMaterHigh() != null) {
                pushDraw.setThickNess(BigDecimal.valueOf(orderBom.getMaterHigh()));
            } else {
                pushDraw.setThickNess(BigDecimal.valueOf(Integer.parseInt(split[1])));
            }
            if (CollUtil.isNotEmpty(orderParts)) {
                OrderPart orderPart = orderParts.get(0);

                pushDraw.setFilePath(orderPart.getDxfUrl());
                pushDraw.setStatus(1);
                pushDraw.setErrorMsg(null);
                pushDraw.setUniMaterCode(orderBom.getPlmId() + "#" + orderPart.getVersionNum());
                pushDraw.setDrawVersion(orderPart.getVersionNum());
            } else {
                pushDraw.setFilePath(null);
                pushDraw.setStatus(5);
                pushDraw.setErrorMsg("缺少下料DXF图。");
                pushDraw.setUniMaterCode(orderBom.getPlmId() + "#" + "A.0");
                pushDraw.setDrawVersion("A.0");
            }

            sinoCamPushDraws.add(pushDraw);
        }

        if (CollUtil.isNotEmpty(sinoCamPushDraws)) {
            sinoCamPushDrawingMapper.insertBatchSomeColumn(sinoCamPushDraws);
        }

    }

    @Override
    public void partPush() {

        try {
            fixPart();
        } catch (Exception e) {
        }

        List<SinoCamPushDrawing> lantekPushDrawList = sinoCamPushDrawingMapper.lambdaQuery()
                .and(wr->wr.ne(SinoCamPushDrawing::getDrawVersion, "A.0").or().isNotNull(SinoCamPushDrawing::getDrawVersion))
                .eq(SinoCamPushDrawing::getStatus, 1)
                .list();

        List<LantekPreDrawInfoVo> pushVoList = new ArrayList<>();

        for (SinoCamPushDrawing draw : lantekPushDrawList) {
            LantekPreDrawInfoVo vo = new LantekPreDrawInfoVo();
            vo.setUniMaterCode(draw.getUniMaterCode());
            vo.setMaterName(draw.getPartName());
            vo.setTexture(draw.getTexture());
            vo.setThickness(draw.getThickNess().intValue());
            vo.setDxfPath(dxfDownload + draw.getFilePath());
            pushVoList.add(vo);
        }
        if (CollUtil.isEmpty(pushVoList)) {
            return ;
        }
        LantekPreDrawReqVo pushVo = new LantekPreDrawReqVo();
        pushVo.setParts(pushVoList);
        log.info("推送信息：{}", JsonUtils.toJsonString(pushVo));
        NestLanCommonsResVo pro = lantekProApiClient.registerOrUpdate(pushVo, LtkPushTokenDto.TOKEN);
        log.info("推送结果：{}", JsonUtils.toJsonString(pro));
        int res = 0;
        if (pro.getCode() == 200) {
            res = 4;
        } else {
            res = 5;
        }
        for (SinoCamPushDrawing draw : lantekPushDrawList) {
            draw.setStatus(res);
            sinoCamPushDrawingMapper.updateById(draw);
        }

    }

    public void fixPart() {
        List<SinoCamPushDrawing> lantekPushDrawList = sinoCamPushDrawingMapper.lambdaQuery()
                .and(wr -> wr.eq(SinoCamPushDrawing::getDrawVersion, "A.0").or().isNull(SinoCamPushDrawing::getDrawVersion))
                .list();
        List<OrderPart> orderPartList = orderPartMapper.lambdaQuery()
                .in(OrderPart::getPlmId, lantekPushDrawList.stream().map(SinoCamPushDrawing::getPartId).collect(Collectors.toList()))
                .list();
        Map<String, List<OrderPart>> orderPartMap = orderPartList.stream().collect(Collectors.groupingBy(OrderPart::getPlmId));

        for (SinoCamPushDrawing draw : lantekPushDrawList) {
            List<OrderPart> orderParts = orderPartMap.get(draw.getPartId());
            if (orderParts.stream().anyMatch(e -> e.getDxfUrl() != null)) {
                List<OrderPart> collect = orderParts.stream()
                        .filter(e -> e.getDxfUrl() != null)
                        .sorted(Comparator.comparing(OrderPart::getDrawUpdateTime).reversed())
                        .collect(Collectors.toList());
                OrderPart orderPart = collect.get(0);
                draw.setFilePath(orderPart.getDxfUrl());
                draw.setUniMaterCode(draw.getPartId() + "#" + orderPart.getVersionNum());
                draw.setDrawVersion(orderPart.getVersionNum());
                draw.setStatus(1);
                draw.setVersionNum(draw.getVersionNum() + 1);
                sinoCamPushDrawingMapper.updateById(draw);
            }
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void planAdd(List<ApsWorkDetail> detailList, List<OrderBom> bomList, Object object) {

        if (CollUtil.isEmpty(detailList)) {
            return;
        }

        List<ApsWorkDetail> apsWorkDetailList = detailList;

        List<Integer> orderIds = apsWorkDetailList.stream().map(ApsWorkDetail::getOrderId).collect(Collectors.toList());

        List<ApsOrder> apsOrders = apsOrderMapper.lambdaQuery().in(ApsOrder::getOrderId, orderIds).list();
        Map<Integer, ApsOrder> apsOrderIdMap = apsOrders.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        // 取 ID
        List<ApsWorkOrder> apsWorkOrders = apsWorkOrderMapper.selectBatchIds(apsWorkDetailList.stream().map(ApsWorkDetail::getApsWorkOrderId).distinct().collect(Collectors.toList()));
        Map<Integer, ApsWorkOrder> apsWorkOrderIdMap = apsWorkOrders.stream().collect(Collectors.toMap(ApsWorkOrder::getId, Function.identity()));

        // 取 PID
        List<ApsWorkOrder> parentApsWorkOrders = apsWorkOrderMapper.selectBatchIds(apsWorkDetailList.stream().map(ApsWorkDetail::getApsWorkOrderPid).distinct().collect(Collectors.toList()));
        Map<Integer, ApsWorkOrder> apsWorkOrderPidMap = parentApsWorkOrders.stream().collect(Collectors.toMap(ApsWorkOrder::getId, Function.identity()));

        // 获取工厂信息
        List<Factory> factoryList = factoryMapper.selectList(null);
        Map<Integer, Factory> factoryMap = factoryList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<Order> orderList = orderMapper.lambdaQuery().in(BaseEntity::getId, orderIds).list();

        // 保存计划信息
        savePlanInfo(apsWorkDetailList, factoryMap, orderList, apsOrderIdMap, apsWorkOrderPidMap, apsWorkOrderIdMap);

    }

    public void savePlanInfo(List<ApsWorkDetail> apsWorkDetailList, Map<Integer, Factory> factoryMap, List<Order> orderList, Map<Integer, ApsOrder> apsOrderIdMap, Map<Integer, ApsWorkOrder> apsWorkOrderPidMap, Map<Integer, ApsWorkOrder> apsWorkOrderIdMap) {

        List<SinoCamPushDrawing> sinoCamPushPushDrawList = sinoCamPushDrawingMapper.lambdaQuery().in(SinoCamPushDrawing::getPartId, apsWorkDetailList.stream().map(ApsWorkDetail::getPlmId).collect(Collectors.toList())).list();
        Map<String, SinoCamPushDrawing> sinoCamPushPushDrawMap = sinoCamPushPushDrawList.stream().collect(Collectors.toMap(SinoCamPushDrawing::getPartId, Function.identity(), (a, b) -> b));

        Map<Integer, Order> orderMap = orderList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<ApsWorkOrder> allApsWorkOrder = apsWorkOrderMapper.lambdaQuery().in(ApsWorkOrder::getOrderId, orderList.stream().map(Order::getId).collect(Collectors.toList())).list();
        Map<Integer, List<ApsWorkOrder>> orderApsWorkOrder = allApsWorkOrder.stream().collect(Collectors.groupingBy(ApsWorkOrder::getOrderId));
        Map<Integer, Map<Integer, ApsWorkOrder>> allApsWorkOrderMap = new HashMap<>();
        for (Integer orderId : orderApsWorkOrder.keySet()) {
            List<ApsWorkOrder> orderApsWorkOrderMap = orderApsWorkOrder.get(orderId);
            Map<Integer, ApsWorkOrder> apsWorkOrderMap = orderApsWorkOrderMap.stream().collect(Collectors.toMap(ApsWorkOrder::getId, Function.identity()));
            allApsWorkOrderMap.put(orderId, apsWorkOrderMap);
        }

        List<SinoCamPushPlan> pushPlans = sinoCamPushPlanMapper.lambdaQuery().in(SinoCamPushPlan::getOrderId, orderList.stream().map(Order::getId).collect(Collectors.toList())).list();
        Map<String, SinoCamPushPlan> pushPlanMap = pushPlans.stream().collect(Collectors.toMap(SinoCamPushPlan::getNestPlanId, Function.identity()));

        List<SinoCamPushPlan> pushPlanList = new ArrayList<>();
        // 构建推送参数和数据库记录信息
        for (ApsWorkDetail apsWorkDetail : apsWorkDetailList) {

            SinoCamPushPlan pushPlan = new SinoCamPushPlan();

            ApsWorkOrder current = apsWorkOrderIdMap.get(apsWorkDetail.getApsWorkOrderId());
            ApsWorkOrder parent = apsWorkOrderPidMap.get(current.getPid());
            ApsOrder apsOrder = apsOrderIdMap.get(apsWorkDetail.getApsOrderId());
            Order order = orderMap.get(apsWorkDetail.getOrderId());

            int id = current.getId();
//            String path = PkgUtils.gen(apsOrder.getSeq()) + "→";
            String path = "";
            while (true) {
                Map<Integer, ApsWorkOrder> orderApsWorkOrderMap = allApsWorkOrderMap.get(order.getId());
                ApsWorkOrder pathCur = orderApsWorkOrderMap.get(id);
                if (ObjectUtils.isEmpty(pathCur) || pathCur.getPid() == null) {
//                    path = PkgUtils.gen(apsOrder.getSeq()) + path;
                    break;
                }
                ApsWorkOrder pathPar = orderApsWorkOrderMap.get(pathCur.getPid());
                path = "→" + pathPar.getPlmId() + path;
                id = pathPar.getId();
            }

            SinoCamPushDrawing pushDraw = sinoCamPushPushDrawMap.get(apsWorkDetail.getPlmId());

            pushPlan.setComponentId(parent.getPlmId());
            pushPlan.setComponentName(parent.getMaterName());
            pushPlan.setFactoryIdk(factoryMap.get(apsWorkDetail.getFactoryId()).getMyCode());
            pushPlan.setNeedDate(apsWorkDetail.getPlanStartDateTime());
            pushPlan.setNestPlanId(String.valueOf(apsWorkDetail.getId()));
            pushPlan.setPartId(current.getPlmId());
            pushPlan.setPartName(current.getMaterName());
            pushPlan.setPartType("1");
            pushPlan.setPlanAmount(apsWorkDetail.getTotalCount());
            pushPlan.setProcessingNo(PkgUtils.gen(apsOrder.getSeq()));
            pushPlan.setApsOrderId(apsWorkDetail.getApsOrderId());
            pushPlan.setProductId(StringUtils.hasText(order.getConstructNo())?order.getConstructNo():order.getOrderCode());
            pushPlan.setVersionBrief("V1");
            if (ObjectUtils.isEmpty(pushDraw) || pushDraw.getStatus() == 5) {
                pushPlan.setStatus(5);
                pushPlan.setErrorMsg("推送图纸异常。");
                pushPlan.setUniMaterCode(current.getPlmId() + "#A.0");
                pushPlan.setReplaceTexture(null);
                pushPlan.setReplaceThickness(null);
            } else {
                pushPlan.setStatus(1);
                pushPlan.setErrorMsg(null);
                pushPlan.setUniMaterCode(current.getPlmId() + "#" + pushDraw.getDrawVersion());
                pushPlan.setReplaceTexture(pushDraw.getTexture());
                pushPlan.setReplaceThickness(pushDraw.getThickNess());
            }
            pushPlan.setPlanFinishAmount(new BigDecimal(0));
            pushPlan.setOrderId(order.getId());
            pushPlan.setVersionNum(1);
            pushPlan.setConsumeStatus(0);
            pushPlan.setPath(path);

            pushPlanList.add(pushPlan);

            if (pushPlanMap.get(pushPlan.getNestPlanId()) != null) {
                sinoCamPushPlanMapper.lambdaUpdate().eq(SinoCamPushPlan::getNestPlanId, pushPlan.getNestPlanId()).set(SinoCamPushPlan::getPath, pushPlan.getPath()).update();
                pushPlanList.remove(pushPlan);
            }

        }

        if (CollUtil.isEmpty(pushPlanList)) {
            return ;
        }
        sinoCamPushPlanMapper.insertBatchSomeColumn(pushPlanList);

    }

    /*@Override
    public void pushPlan(List<Integer> ids) {

        if (CollUtil.isEmpty(ids)) {
            return;
        }

        List<NestSpacePart> spacePartList = nestSpacePartMapper.lambdaQuery().in(NestSpacePart::getPartPlanId, ids).eq(NestSpacePart::getStatus, 1).list();
        Map<Integer, NestSpacePart> spacePartMap = spacePartList.stream().collect(Collectors.toMap(NestSpacePart::getPartPlanId, Function.identity()));
        NestSpace nestSpace = nestSpaceMapper.selectById(spacePartList.get(0).getSpaceId());

        List<SinoCamPushPlan> pushPlanList = sinoCamPushPlanMapper.lambdaQuery()
                .in(SinoCamPushPlan::getId, spacePartList.stream().map(NestSpacePart::getPartPlanId).collect(Collectors.toList()))
                .list();

        List<LantekProPlanInfoVo> pushVoList = new ArrayList<>();

        for (SinoCamPushPlan plan : pushPlanList) {
            LantekProPlanInfoVo vo = new LantekProPlanInfoVo();

            NestSpacePart nestSpacePart = spacePartMap.get(plan.getId());

            vo.setPlanId(plan.getNestPlanId());
            vo.setUniMaterCode(plan.getUniMaterCode());
            vo.setPackageCode(plan.getProcessingNo());
            vo.setPlanAmount(nestSpacePart.getTotalCount());
            vo.setNeedDateTime(String.valueOf(plan.getNeedDate()));
            vo.setTexture(plan.getReplaceTexture());
            vo.setThickness(String.valueOf(plan.getReplaceThickness()));
            vo.setDxfPath(null);
            vo.setOrderId(plan.getOrderId() + "_1");

            pushVoList.add(vo);
        }

        if (CollUtil.isEmpty(pushVoList)) {
            return ;
        }
        LantekProPushReqVo pushVo = new LantekProPushReqVo();
        pushVo.setJobRef(nestSpace.getLantekCode());
        // pushVo.setUsername("Powersync");
        pushVo.setUsername(nestSpace.getCreateUsername());
        pushVo.setOrders(pushVoList);
        log.info("推送套料信息：{}", JsonUtils.toJsonString(pushVo));
        NestLanCommonsResVo pro = lantekProApiClient.clientNesting(pushVo, LtkPushTokenDto.TOKEN);
        log.info("推送套料结果：{}", JsonUtils.toJsonString(pro));
        int res = 0;
        if (pro.getCode() == 200) {
            res = 4;
        } else {
            res = 5;
        }
        for (SinoCamPushPlan plan : pushPlanList) {
            plan.setStatus(res);
            sinoCamPushPlanMapper.updateById(plan);
        }

        if (pro.getCode() == 200) {
            nestSpace.setLantekCode(StringUtils.isEmpty(nestSpace.getLantekCode())?pro.getResult(): nestSpace.getLantekCode());
            nestSpace.setStatus(2);
            nestSpaceMapper.updateById(nestSpace);

            for (NestSpacePart nestSpacePart : spacePartList) {
                nestSpacePart.setStatus(2);
                nestSpacePartMapper.updateById(nestSpacePart);
            }
        } else {
            throw SyExceptionUtils.e("计划导入兰特克套料软件失败：{}", pro.getMessage());
        }

    }*/

    @Override
    public void planPush(List<Integer> ids, String groupCode, Integer spaceId) {

        String userCode = SySecurityUtils.getUserCode();

        if (CollUtil.isEmpty(ids)) {
            return;
        }

        List<SinoCamPushPlan> pushPlanList = sinoCamPushPlanMapper.lambdaQuery()
                .in(SinoCamPushPlan::getId, ids)
                .list();

        List<String> textureList = pushPlanList.stream().map(SinoCamPushPlan::getReplaceTexture).collect(Collectors.toList());
        List<BigDecimal> thicknessList = pushPlanList.stream().map(SinoCamPushPlan::getReplaceThickness).collect(Collectors.toList());

        NestSpace nestSpace = new NestSpace();
        if (spaceId == null) {
            nestSpace = createWorkPlace(textureList.get(0), thicknessList.get(0).intValue(), groupCode);
        } else {
            nestSpace = nestSpaceMapper.selectById(spaceId);
            NestSpace finalNestSpace = nestSpace;
            if (pushPlanList.stream().anyMatch(e->e.getReplaceThickness().intValue()!=Integer.parseInt(finalNestSpace.getThickness()))) {
                throw SyExceptionUtils.e("厚度与作业区厚度不符：{}", nestSpace.getSpaceCode());
            }
        }

        List<LantekProPlanInfoVo> pushVoList = new ArrayList<>();

        for (SinoCamPushPlan plan : pushPlanList) {
            LantekProPlanInfoVo vo = new LantekProPlanInfoVo();

            vo.setPlanId(plan.getNestPlanId());
            vo.setUniMaterCode(plan.getUniMaterCode());
            vo.setPackageCode(plan.getProcessingNo());
            vo.setPlanAmount(plan.getPlanAmount().intValue() - plan.getPlanFinishAmount().intValue());
            vo.setNeedDateTime(String.valueOf(plan.getNeedDate()));
            if (ObjectUtil.equals(plan.getReplaceTexture(), nestSpace.getTexture())) {
                vo.setTexture(plan.getReplaceTexture());
            } else {
                vo.setTexture(nestSpace.getTexture()); // 作业区材质
                vo.setRawTexture(plan.getReplaceTexture()); // 零件原本材质
            }
            vo.setThickness(String.valueOf(plan.getReplaceThickness()));
            vo.setDxfPath(null);
            vo.setOrderId(plan.getOrderId() + "_1");

            pushVoList.add(vo);
        }

        if (CollUtil.isEmpty(pushVoList)) {
            return ;
        }

        LantekProPushReqVo pushVo = new LantekProPushReqVo();
        // pushVo.setUsername("Powersync");
        pushVo.setJobRef(nestSpace.getLantekCode());
        pushVo.setUsername(userCode);
        pushVo.setWrkRef(nestSpace.getGroupCode());
        pushVo.setOrders(pushVoList);
        log.info("推送套料信息：{}", JsonUtils.toJsonString(pushVo));
        Request.Options options = new Request.Options(120L, TimeUnit.SECONDS, 120L, TimeUnit.SECONDS, true);
        NestLanCommonsResVo pro = lantekProApiClient.clientNesting(pushVo, LtkPushTokenDto.TOKEN, options);
        log.info("推送套料结果：{}", JsonUtils.toJsonString(pro));
        int res = 0;
        if (pro.getCode() == 200) {
            res = 4;
        } else {
            res = 5;
        }
        for (SinoCamPushPlan plan : pushPlanList) {
            plan.setStatus(res);
            sinoCamPushPlanMapper.updateById(plan);
        }

        if (pro.getCode() == 200 && StringUtils.hasText(pro.getResult())) {
            // 成功后返回作业区编码，没有就新建，有就新增作业区下绑定的零件列表
            List<NestSpacePart> partList = new ArrayList<>();
            for (SinoCamPushPlan plan : pushPlanList) {
                NestSpacePart spacePart = new NestSpacePart();
                spacePart.setFinishCount(0);
                spacePart.setPartPlanId(plan.getId());
                spacePart.setSpaceId(nestSpace.getId());
                spacePart.setTotalCount(plan.getPlanAmount().intValue() - plan.getPlanFinishAmount().intValue());
                spacePart.setStatus(2);
                partList.add(spacePart);

//                ApsWorkDetail detail = apsWorkDetailMapper.selectById(plan.getNestPlanId());
//                ApsWorkOrder workOrder = apsWorkOrderMapper.selectById(detail.getApsWorkOrderId());
//                if (StringUtils.hasText(workOrder.getPickCode())) {
//                    if (!workOrder.getPickCode().contains("兰特克")) {
//                        workOrder.setPickCode(workOrder.getPickCode() + "兰特克,");
//                    }
//                } else {
//                    workOrder.setPickCode("兰特克,");
//                }
//                workOrder.setPickSeq(workOrder.getPickSeq() + (plan.getPlanAmount().intValue() - plan.getPlanFinishAmount().intValue()));
//                apsWorkOrderMapper.updateById(workOrder);
            }
            nestSpacePartMapper.insertBatchSomeColumn(partList);
        } else {
            throw SyExceptionUtils.e("计划导入兰特克套料软件失败：{}", pro.getMessage());
        }

    }

    @Transactional
    public NestSpace createWorkPlace(String texture, Integer thickness, String groupCode) {
        String userCode = SySecurityUtils.getUserCode();

        // 每天 6 点之前算前一天的作业区
        // TODO 调用作业区关闭的接口，释放零件和钢板，关闭作业区
        List<NestSpace> nestSpaceList = nestSpaceMapper.lambdaQuery()
                .eq(NestSpace::getStatus, 2)
                .eq(NestSpace::getCreateUsername, userCode)
                .lt(NestSpace::getCreateDateTime, LocalDate.now() + " 06:00:00")
                .list();
        if (CollUtil.isNotEmpty(nestSpaceList)) {

            for (NestSpace p : nestSpaceList) {
                p.setStatus(3);
                nestSpaceMapper.updateById(p);
            }
            nestSpacePartMapper.lambdaUpdate()
                    .eq(NestSpacePart::getStatus, 2)
                    .in(NestSpacePart::getSpaceId, nestSpaceList.stream().map(NestSpace::getId).collect(Collectors.toList()))
                    .set(NestSpacePart::getStatus, 3)
                    .set(NestSpacePart::getModifyDateTime, LocalDateTime.now())
                    .update();
            nestSpacePlateMapper.lambdaUpdate()
                    .eq(NestSpacePlate::getStatus, 2)
                    .in(NestSpacePlate::getSpaceId, nestSpaceList.stream().map(NestSpace::getId).collect(Collectors.toList()))
                    .set(NestSpacePlate::getStatus, 3)
                    .set(NestSpacePlate::getModifyDateTime, LocalDateTime.now())
                    .update();
        }

        NestSpace nestSpace = nestSpaceMapper.lambdaQuery()
                .eq(NestSpace::getCreateUsername, userCode)
                .eq(NestSpace::getStatus, 2)
                .eq(NestSpace::getTexture, texture)
                .eq(NestSpace::getThickness, thickness)
                .one();

        nestSpaceMapper.lambdaUpdate()
                .eq(NestSpace::getCreateUsername, userCode)
                .eq(NestSpace::getStatus, 2)
                .and(w->w.ne(NestSpace::getTexture, texture).or().ne(NestSpace::getThickness, thickness))
                .set(NestSpace::getStatus, 3)
                .update();

        if (ObjectUtils.isEmpty(nestSpace)) {
            NestSpace newSpace = new NestSpace();
            String spaceCode = texture + "-" + thickness + "-" + userCode + "-" + TimeSplitUtils.nestDateName();
            newSpace.setTexture(texture);
            newSpace.setThickness(String.valueOf(thickness));
            newSpace.setGroupCode(groupCode);
            newSpace.setSpaceCode(spaceCode);
            newSpace.setStatus(2);

            WorkSpaceCreateReqVo reqVo = new WorkSpaceCreateReqVo();
            reqVo.setJobRef(spaceCode);
            NestLanCommonsResVo pro = lantekProApiClient.jobCreate(reqVo, LtkPushTokenDto.TOKEN);
            if (pro.getCode() != 200 || !StringUtils.hasText(pro.getResult())) {
                throw SyExceptionUtils.e("作业区创建失败");
            } else {
                newSpace.setLantekCode(pro.getResult());
            }
            nestSpaceMapper.insert(newSpace);
            return newSpace;
        } else {
            return nestSpace;
        }
    }

    /*@Override
    public void pushPlates(Integer spaceId, List<String> plateCodes) {

        if (CollUtil.isEmpty(plateCodes)) {
            return;
        }

        NestPlatePushReqVo pushVo = new NestPlatePushReqVo();
        List<NestPlatePushInfoVo> plateInfoList = new ArrayList<>();

        NestSpace nestSpace = nestSpaceMapper.selectById(spaceId);

        PlateListReqVo wmsPlateReqVo = new PlateListReqVo();
        wmsPlateReqVo.setPlateCodes(plateCodes);
        Result<Page<PlateListResVo>> pageResult = apsWmsApiClient.plateList(wmsPlateReqVo);
        Page<PlateListResVo> data = pageResult.getData();
        List<PlateListResVo> records = data.getRecords();
        for (PlateListResVo record : records) {
            NestPlatePushInfoVo vo = new NestPlatePushInfoVo();
            vo.setPlateCode(record.getPlateId());
            vo.setMaterielName(record.getPlateId());
            vo.setAmount(1);
            vo.setLength(record.getLength().intValue());
            vo.setWidth(record.getWidth().intValue());
            vo.setThickness(record.getThickness().intValue());
            vo.setTexture(record.getTexture());
            vo.setFactoryCode("170");
            vo.setSequence(record.getLayer());
            vo.setStoreCode("170");
            vo.setPositionCode(record.getStockId());
            plateInfoList.add(vo);
        }
        pushVo.setSteelPlates(plateInfoList);
        pushVo.setJobRef(nestSpace.getLantekCode());
        log.info("推送钢板信息：{}", JsonUtils.toJsonString(pushVo));
        NestLanCommonsResVo pro = lantekProApiClient.importAPSIntegratedInventory(pushVo, LtkPushTokenDto.TOKEN);
        log.info("推送钢板结果：{}", JsonUtils.toJsonString(pro));

        if (pro.getCode() == 200) {
            List<NestSpacePlate> spacePlateList = nestSpacePlateMapper.lambdaQuery().eq(NestSpacePlate::getSpaceId, spaceId).in(NestSpacePlate::getPlateCode, plateCodes).list();
            for (NestSpacePlate spacePlate : spacePlateList) {
                spacePlate.setStatus(2);
                nestSpacePlateMapper.updateById(spacePlate);
            }
            // 改变 WMS 中的钢板状态
            LantekLockStockReqVo stockLockVo = new LantekLockStockReqVo();
            stockLockVo.setPlateList(plateCodes);
            apsWmsApiClient.pushLanLock(stockLockVo);
        } else {
            throw SyExceptionUtils.e("钢板导入兰特克套料软件失败：{}", pro.getMessage());
        }
    }*/

    @Override
    public void platesPush(Integer spaceId, List<String> plateCodes) {

        String userCode = SySecurityUtils.getUserCode();
        DictType personBind = dictTypeMapper.lambdaQuery().eq(DictType::getDictCode, "personBind").one();
        List<DictData> personBindList = dictDataMapper.lambdaQuery().eq(DictData::getDictType, personBind.getId()).list();
        Map<String, DictData> personBindMap = personBindList.stream().collect(Collectors.toMap(DictData::getDictLabel, v -> v));
        String userName = personBindMap.get(userCode).getDictValue();

        if (CollUtil.isEmpty(plateCodes)) {
            return;
        }

        NestSpace nestSpace = nestSpaceMapper.lambdaQuery().eq(NestSpace::getCreateUsername, userCode).eq(NestSpace::getStatus, 2).one();
        if (ObjectUtils.isEmpty(nestSpace)) {
            throw SyExceptionUtils.e("未查询到套料中的作业区：{}", userName);
        }

        List<NestPlatePushInfoVo> plateInfoList = new ArrayList<>();

        PlateListReqVo wmsPlateReqVo = new PlateListReqVo();
        wmsPlateReqVo.setPlateCodes(plateCodes);
        wmsPlateReqVo.setPlateStock(1);
        Result<Page<PlateListResVo>> pageResult = apsWmsApiClient.plateList(wmsPlateReqVo);
        Page<PlateListResVo> data = pageResult.getData();
        List<PlateListResVo> records = data.getRecords();

        if (records.stream().anyMatch(e->!e.getTexture().equals(nestSpace.getTexture()))) {
            throw SyExceptionUtils.e("材质与作业区不匹配：{}", nestSpace.getSpaceCode());
        }
        if (records.stream().anyMatch(e->e.getThickness().intValue() != (Integer.parseInt(nestSpace.getThickness())))) {
            throw SyExceptionUtils.e("厚度与作业区不匹配：{}", nestSpace.getSpaceCode());
        }

        for (PlateListResVo record : records) {
            NestPlatePushInfoVo vo = new NestPlatePushInfoVo();
            vo.setPlateCode(record.getPlateId());
            vo.setMaterielName(record.getPlateId());
            vo.setAmount(1);
            vo.setLength(record.getLength().intValue());
            vo.setWidth(record.getWidth().intValue());
            vo.setThickness(record.getThickness().intValue());
            vo.setTexture(record.getTexture());
            vo.setFactoryCode("170");
            vo.setSequence(record.getLayer());
            vo.setStoreCode("170");
            vo.setPositionCode(record.getStockId());
            plateInfoList.add(vo);
        }
        NestPlatePushReqVo pushVo = new NestPlatePushReqVo();
        pushVo.setJobRef(nestSpace.getLantekCode());
        pushVo.setUsername(userCode);
        pushVo.setSteelPlates(plateInfoList);
        log.info("推送钢板信息：{}", JsonUtils.toJsonString(pushVo));
        NestLanCommonsResVo pro = lantekProApiClient.importAPSIntegratedInventory(pushVo, LtkPushTokenDto.TOKEN);
        log.info("推送钢板结果：{}", JsonUtils.toJsonString(pro));

        if (pro.getCode() == 200 && StringUtils.hasText(pro.getResult())) {
            List<NestSpacePlate> plateList = new ArrayList<>();
            for (PlateListResVo vo : records) {
                NestSpacePlate spacePlate = new NestSpacePlate();
                spacePlate.setPlateCode(vo.getPlateId());
                spacePlate.setSpaceId(nestSpace.getId());
                spacePlate.setStatus(2);
                spacePlate.setCount(1);
                plateList.add(spacePlate);
            }
            nestSpacePlateMapper.insertBatchSomeColumn(plateList);

            // 改变 WMS 中的钢板状态
            LantekLockStockReqVo stockLockVo = new LantekLockStockReqVo();
            stockLockVo.setPlateList(plateCodes);
            apsWmsApiClient.pushLanLock(stockLockVo);
        } else {
            throw SyExceptionUtils.e("钢板导入兰特克套料软件失败：{}", pro.getMessage());
        }
    }

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public void nestReceive(String body) {

        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, LantekReceiveNestReqVo.class);
        List<LantekReceiveNestReqVo> reqVo = objectMapper.readValue(body, javaType);

        receiveNest(reqVo);

    }

    @Transactional(rollbackFor = Exception.class)
    public void receiveNest(List<LantekReceiveNestReqVo> reqVo) {
//        LantekReceiveNestNestReqVo nest = reqVo.get(0).getNest();
//        List<LantekReceiveNestPlateReqVo> plateList = reqVo.get(0).getPlate();
//        List<LantekReceiveNestPartReqVo> partList = reqVo.get(0).getPart();
//        List<LantekReceiveNestExcessReqVo> excessList = reqVo.get(0).getExcess();
//        List<LantekReceiveNestMoveReqVo> moveList = reqVo.get(0).getMove();
//
//        String jobRef = nest.getJobRef();
//        NestSpace nestSpace = nestSpaceMapper.lambdaQuery().eq(NestSpace::getLantekCode, jobRef).one();
//        List<NestSpacePart> spacePartList = nestSpacePartMapper.lambdaQuery().eq(NestSpacePart::getSpaceId, nestSpace.getId()).list();
//
//        List<SinoCamPushPlan> pushPlanList = sinoCamPushPlanMapper.lambdaQuery().in(SinoCamPushPlan::getId, spacePartList.stream().map(NestSpacePart::getPartPlanId).collect(Collectors.toList())).list();

        // 接收套料结果，数据进行回填。
        // 套料 nest（套料信息），plate（钢板信息列表），part（套料零件列表），excess（钢板余料列表），move（套料切割信息）。
        // 计划 aps_work_detail（钢板四个工序计划），plate_phase（钢板四个工序信息），mes_plate（钢板信息），mes_plate_pick（钢板领料信息），mes_work_detail_task（钢板领料任务）。
        // 计划回填 pushPlan（回填计划套料完成数量），nestSpacePart（回填作业区零件完成数量，及套料完成状态），计划状态修改（如果完成数量等于推送数量则状态置为完成）


        Map<String, List<SinoCamReceiveNestPart>> partMap = new HashMap<>();

        for (LantekReceiveNestReqVo vo : reqVo) {
            SinoCamReceiveNestNest nn = sinoCamReceiveNestNestMapper.lambdaQuery().eq(SinoCamReceiveNestNest::getNestId, vo.getNest().getNestId()).one();
            if (nn != null) {
                throw SyExceptionUtils.e("套料图号重复：{}", vo.getNest().getNestId());
//                continue;
            }

            // 套料
            LantekReceiveNestNestReqVo nest = vo.getNest();

            NestSpace nestSpace = nestSpaceMapper.lambdaQuery().eq(NestSpace::getLantekCode, nest.getJobRef()).one();

            SinoCamReceiveNestNest nestEntity = MkBeanUtils.copyProperties(nest, SinoCamReceiveNestNest.class);
            nestEntity.setNestId(nest.getNestId());
            nestEntity.setLantekCode(nest.getJobRef());
            nestEntity.setFactoryIdk("170");
            nestEntity.setCutLength(nest.getCutLength());
            nestEntity.setCutNozzleNorm(nest.getCutNozzleNorm());
            nestEntity.setCutNozzleNumber(nest.getCutNozzleNumber());
            nestEntity.setCutNozzleDistance(nest.getCutNozzleDistance());
            nestEntity.setWidth(nest.getWidth());
            nestEntity.setLength(nest.getLength());
            nestEntity.setNestDate(nest.getNestDateTime());
            nestEntity.setNeedDate(nest.getNeedDateTime());
            nestEntity.setNester(nest.getNester());
            nestEntity.setOptionId(nest.getOptionId());
            nestEntity.setSplitGroupCode(nest.getOptionId());
            nestEntity.setNestDxfUrl(nest.getDxfUrl());
            nestEntity.setBookSheet(nest.getBookSheet());
            nestEntity.setReportPdfUrl(nest.getReportPdfUrl());
            nestEntity.setCuttingProgramUrl(nest.getCuttingProgramUrl());
            nestEntity.setRate(nest.getRate()); // 利用率，钢板减去余料，再与零件重量进行计算，得到利用率
            nestEntity.setVersionBrief("V2");

            sinoCamReceiveNestNestMapper.insert(nestEntity);

            log.info("套料:{}", JsonUtils.toJsonString(nestEntity));

            // 零件
            List<SinoCamReceiveNestPart> parts = vo.getPart().stream()
                    .map(e -> {
                        SinoCamReceiveNestPart part = MkBeanUtils.copyProperties(e, SinoCamReceiveNestPart.class);
                        String orderId = e.getOrderId();
                        String[] split = orderId.split("_");
                        part.setNestId(vo.getNest().getNestId());
                        part.setNestPlanId(e.getPartPlanId());
                        part.setUniCode(split[0] + "#" + e.getPartId());
                        part.setPartName(e.getPartName());
                        part.setQuantity(e.getQuantity());
                        part.setNetWeight(e.getNetWeight());
                        part.setArea(e.getArea());
                        part.setRectangleArea(e.getRectangleArea());
                        part.setRequireFactoryId("170");
                        part.setWidth(e.getWidth());
                        part.setLength(e.getLength());
                        part.setThickness(e.getThickness());
                        part.setPartMapUrl(e.getPngUrl());
                        part.setPlateCode(e.getPlateCode());
                        part.setSortingCount(0);// 分拣数量
                        part.setSortState(0);
                        part.setOrderId(Integer.parseInt(split[0]));
                        if (e.getPartId().contains("#")) {
                            part.setPartId(e.getPartId().split("#")[0]);
                        } else {
                            part.setPartId(e.getPartId());
                        }

                        return part;
                    })
                    .collect(Collectors.toList());

            for (SinoCamReceiveNestPart part : parts) {
                partMap.computeIfAbsent(part.getNestPlanId(), kk -> new ArrayList<>()).add(part);
            }

            sinoCamReceiveNestPartMapper.insertBatchSomeColumn(parts);

            log.info("零件:{}", JsonUtils.toJsonString(parts));

            // 钢板
            if (vo.getPlate().size() > 2) {
                throw SyExceptionUtils.e("钢板数量大于2");
            }

            List<String> collect1 = vo.getPlate().stream().map(LantekReceiveNestPlateReqVo::getPlateCode).collect(Collectors.toList());

            Integer count = sinoCamReceiveNestPlateMapper.lambdaQuery().in(SinoCamReceiveNestPlate::getStockListNo, collect1).count();
            if (count > 0) {
                throw SyExceptionUtils.e("钢板重复");
            }

            List<SinoCamReceiveNestPlate> plates = vo.getPlate()
                    .stream()
                    .map(e -> {
                        SinoCamReceiveNestPlate plate = MkBeanUtils.copyProperties(e, SinoCamReceiveNestPlate.class);
                        plate.setAmount(BigDecimal.ONE);
                        plate.setHeatNumber(e.getHeatId()); // 炉批号需要去 WMS 查询
                        plate.setNestId(vo.getNest().getNestId());
                        plate.setStockListNo(e.getPlateCode());
                        plate.setMaterielName(e.getPlateCode());
                        plate.setFactoryIdk(e.getFactoryCode());
                        plate.setTexture(e.getTexture());
                        plate.setNorm(e.getThickness().toString());
                        plate.setWidth(e.getWidth());
                        plate.setLength(e.getLength());
                        plate.setStorehouseId(e.getStoreCode());
                        plate.setSequence(e.getSequence());
                        plate.setLayer(e.getSequence());
                        plate.setIsVirtual(vo.getNest().getPlanType() == 1);
                        plate.setEmptyCutLength(e.getEmptyCutLength());
                        plate.setCutTime(e.getCutTime());
                        plate.setTotalCutLength(e.getTotalCutLength());
                        plate.setRate(vo.getNest().getRate());
                        plate.setHoleCount(e.getHoleCount());
                        plate.setSideLength(vo.getNest().getSideLength());
                        plate.setStatus(1);// 领料状态
                        plate.setPngUrl(e.getPngUrl());
                        plate.setPositionCode(e.getPositionCode());
                        plate.setNestArea(e.getNestArea());

                        return plate;
                    })
                    .collect(Collectors.toList());

            sinoCamReceiveNestPlateMapper.insertBatchSomeColumn(plates);

            log.info("钢板:{}", JsonUtils.toJsonString(plates));

            // 余料
            List<SinoCamReceiveNestExcess> excess = vo.getExcess()
                    .stream()
                    .map(e -> {
                        SinoCamReceiveNestExcess plate = MkBeanUtils.copyProperties(e, SinoCamReceiveNestExcess.class);
                        plate.setNestId(vo.getNest().getNestId());
                        plate.setFactoryIdk("170");
                        plate.setStockListNo(e.getPlateCode());
                        plate.setExMaterielId(e.getExcessCode());
                        plate.setTexture(e.getTexture());
                        plate.setNorm(e.getThickness().toString());
                        plate.setWidth(e.getWidth());
                        plate.setLength(e.getLength());
                        plate.setWeight(e.getWeight());
                        plate.setOutStock(0);

                        return plate;
                    })
                    .collect(Collectors.toList());
            if (CollUtil.isNotEmpty(excess)) {
                sinoCamReceiveNestExcessMapper.insertBatchSomeColumn(excess);
            }

            log.info("余料:{}", JsonUtils.toJsonString(excess));

            // 走刀
            List<SinoCamReceiveNestMove> moves = vo.getMove()
                    .stream()
                    .map(e -> {
                        SinoCamReceiveNestMove move = MkBeanUtils.copyProperties(e, SinoCamReceiveNestMove.class);
                        move.setNestId(vo.getNest().getNestId());
                        move.setCutLength(e.getCutLength().multiply(BigDecimal.valueOf(1000)));
                        move.setFactoryIdk(e.getFactoryCode());
                        move.setMoveTime(e.getMoveTime());
                        move.setMoveType(e.getMoveType());
                        move.setHoleCount(e.getHoleCount());
                        move.setHoleTime(e.getHoleTime());
                        move.setTotalHoleTime(e.getTotalHoleTime());
                        move.setCutRate(e.getCutRate().multiply(BigDecimal.valueOf(1000)));
                        move.setTotalCutTime(e.getTotalCutTime());

                        return move;
                    })
                    .collect(Collectors.toList());

            sinoCamReceiveNestMoveMapper.insertBatchSomeColumn(moves);

            List<Integer> planIdList = vo.getPart().stream().map(e -> Integer.parseInt(e.getPartPlanId())).distinct().collect(Collectors.toList());
            List<ApsWorkDetail> apsWorkDetails = apsWorkDetailMapper.selectBatchIds(planIdList);


            // ---------- 推送到钢板信息表----
            Map<String, List<SinoCamReceiveNestPart>> nestPartsMap = parts.stream().collect(Collectors.groupingBy(SinoCamReceiveNestPart::getPlateCode));
            List<PlatePhase> platePhaseList = new ArrayList<>();
            List<ApsWorkDetail> apsWorkDetailList = new ArrayList<>();
            Map<String, PlatePhase> plateLlPhaseMap = new HashMap<>();
            List<Plate> plateList = plates.stream().map(nestPlate -> {

                List<SinoCamReceiveNestPart> nestParts = nestPartsMap.get(nestPlate.getStockListNo());
                Plate plate = new Plate();
                plate.setMaterCode(nestPlate.getStockListNo());// 钢板编号
                plate.setMaterName(nestPlate.getMaterielName());// 钢板物料名称
                plate.setLength(nestPlate.getLength());
                plate.setWidth(nestPlate.getWidth());
                plate.setNorm(nestPlate.getNorm());// 厚度
                plate.setTexture(nestPlate.getTexture());
                plate.setStatus(1);
                plate.setHeatNumber(nestPlate.getHeatNumber());

                plate.setNestId(nest.getNestId());
                plate.setCutLength(nest.getCutLength());// 切割长度
                plate.setNestWeight(nestParts.stream().map(part -> part.getNetWeight().multiply(new BigDecimal(part.getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add));
                plate.setNestRate(vo.getNest().getRate());// 利用率
                plate.setNestDateTime(LocalDate.parse(nest.getNestDateTime(), DatePattern.NORM_DATETIME_FORMATTER).atStartOfDay());// 套料日期
                plate.setNestingDrawing(nestPlate.getPngUrl());// 套料图纸，PNG格式
                plate.setCutProcess(nest.getCuttingProgramUrl());// 切割程序下载地址
                // 钢板重量，长*宽*高*密度(7.85)单位 kg
                plate.setWeight(PlateWeightUtils.getPlateWeight(plate.getLength(), plate.getWidth(), plate.getNorm())); // 单位 千克
                plate.setPickDateTime(nestPlate.getPickDateTime());// 领料时间
                plate.setNestPlateId(nestPlate.getId());
                plate.setPhaseCode(WorkshopProp.YC_PHASE_CODE);

                PlatePhase llPhase = new PlatePhase();
                llPhase.setPlateCode(plate.getMaterCode());
                llPhase.setPhaseCode(WorkshopProp.LL_PHASE_CODE);
                llPhase.setPhaseName(WorkshopProp.LL_PHASE_NAME);
                llPhase.setGroupCode(WorkshopProp.LL_GROUP);
                llPhase.setPhaseSeq(platePhaseList.size() + 1);
                platePhaseList.add(llPhase);


                ApsWorkDetail llApsWorkDetail = new ApsWorkDetail();
                llApsWorkDetail.setMaterNo(plate.getMaterCode());
                llApsWorkDetail.setMaterName("钢板");
                llApsWorkDetail.setPhaseId(llPhase.getPhaseSeq());
                llApsWorkDetail.setPhaseSeq(llPhase.getPhaseSeq());
                llApsWorkDetail.setPhaseCode(WorkshopProp.LL_PHASE_CODE);
                llApsWorkDetail.setPartCount(new BigDecimal(1));
                llApsWorkDetail.setFinishCount(new BigDecimal(0));
                llApsWorkDetail.setTotalCount(new BigDecimal(1));
                llApsWorkDetail.setUniqueCode(plate.getMaterCode());
                llApsWorkDetail.setStatus(2);
                llApsWorkDetail.setPhaseName(WorkshopProp.LL_PHASE_NAME);
                llApsWorkDetail.setPlanStartDateTime(DateUtils.parse(nest.getNeedDateTime(), DatePattern.NORM_DATETIME_FORMATTER).toLocalDateTime().minusHours(7));
                llApsWorkDetail.setPlanEndDateTime(DateUtils.parse(nest.getNeedDateTime(), DatePattern.NORM_DATETIME_FORMATTER).toLocalDateTime().minusHours(6));
                llApsWorkDetail.setGroupCode(WorkshopProp.LL_GROUP);
                llApsWorkDetail.setAppendFlag(2);
                llApsWorkDetail.setType(1);
                llApsWorkDetail.setTotalWorkTime(60 * 60);
                llApsWorkDetail.setWorkTime(60 * 60);
                if (CollUtil.isNotEmpty(apsWorkDetails)) {
                    llApsWorkDetail.setOrderId(apsWorkDetails.get(0).getOrderId());
                    llApsWorkDetail.setApsOrderId(apsWorkDetails.get(0).getApsOrderId());
                }
                apsWorkDetailList.add(llApsWorkDetail);

                plateLlPhaseMap.put(plate.getMaterCode(), llPhase);


                // 添加预处理工序
                BigDecimal thickness = new BigDecimal(plate.getNorm());
                if (thickness.compareTo(new BigDecimal(100)) < 0) { //钢板厚度小于100走预处理
                    PlatePhase phase = new PlatePhase();
                    phase.setPlateCode(plate.getMaterCode());
                    phase.setPhaseCode(WorkshopProp.YC_PHASE_CODE);
                    phase.setPhaseName("预处理");
                    phase.setGroupCode(WorkshopProp.YC_GROUP);
                    phase.setPhaseSeq(platePhaseList.size() + 1);
                    platePhaseList.add(phase);
//                    workChain.add(WorkshopProp.YC_PHASE_CODE);
//                    workChainGroupCode.add(WorkshopProp.YC_GROUP);
                    ApsWorkDetail ycApsWorkDetail = new ApsWorkDetail();
                    ycApsWorkDetail.setMaterNo(plate.getMaterCode());
                    ycApsWorkDetail.setMaterName("钢板");
                    ycApsWorkDetail.setPhaseId(phase.getPhaseSeq());
                    ycApsWorkDetail.setPhaseSeq(phase.getPhaseSeq());
                    ycApsWorkDetail.setPhaseCode(WorkshopProp.YC_PHASE_CODE);
                    ycApsWorkDetail.setPartCount(new BigDecimal(1));
                    ycApsWorkDetail.setFinishCount(new BigDecimal(0));
                    ycApsWorkDetail.setTotalCount(new BigDecimal(1));
                    ycApsWorkDetail.setUniqueCode(plate.getMaterCode());
                    ycApsWorkDetail.setStatus(2);
                    ycApsWorkDetail.setPhaseName("预处理");
                    ycApsWorkDetail.setPlanStartDateTime(DateUtils.parse(nest.getNeedDateTime(), DatePattern.NORM_DATETIME_FORMATTER).toLocalDateTime().minusHours(7));
                    ycApsWorkDetail.setPlanEndDateTime(DateUtils.parse(nest.getNeedDateTime(), DatePattern.NORM_DATETIME_FORMATTER).toLocalDateTime().minusHours(6));
                    ycApsWorkDetail.setGroupCode(WorkshopProp.YC_GROUP);
                    ycApsWorkDetail.setAppendFlag(2);
                    ycApsWorkDetail.setType(1);
                    ycApsWorkDetail.setTotalWorkTime(60 * 60);
                    ycApsWorkDetail.setWorkTime(60 * 60);
                    if (CollUtil.isNotEmpty(apsWorkDetails)) {
                        ycApsWorkDetail.setOrderId(apsWorkDetails.get(0).getOrderId());
                        ycApsWorkDetail.setApsOrderId(apsWorkDetails.get(0).getApsOrderId());
                    }
                    apsWorkDetailList.add(ycApsWorkDetail);
                }


                // 添加切割工序
                PlatePhase splitPhase = new PlatePhase();
                splitPhase.setPlateCode(plate.getMaterCode());
                String phaseCode = getSplitCode(nest.getOptionId());
                splitPhase.setPhaseCode(phaseCode);
                splitPhase.setPhaseName(phaseCode.equals("JG") ? "激光切割" : "火焰切割");
                splitPhase.setGroupCode(nest.getOptionId());
                splitPhase.setPhaseSeq(platePhaseList.size() + 1);
                splitPhase.setWorkTime(vo.getMove().get(0).getTotalCutTime());
                platePhaseList.add(splitPhase);

                ApsWorkDetail qgApsWorkDetail = new ApsWorkDetail();
                qgApsWorkDetail.setMaterNo(plate.getMaterCode());
                qgApsWorkDetail.setMaterName("钢板");
                qgApsWorkDetail.setPhaseId(splitPhase.getPhaseSeq());
                qgApsWorkDetail.setPhaseSeq(splitPhase.getPhaseSeq());
                qgApsWorkDetail.setPhaseCode(phaseCode);
                qgApsWorkDetail.setPartCount(new BigDecimal(1));
                qgApsWorkDetail.setFinishCount(new BigDecimal(0));
                qgApsWorkDetail.setTotalCount(new BigDecimal(1));
                qgApsWorkDetail.setUniqueCode(plate.getMaterCode());
                qgApsWorkDetail.setStatus(2);
                qgApsWorkDetail.setPhaseName(phaseCode.equals("JG") ? "激光切割" : "火焰切割");
                qgApsWorkDetail.setPlanStartDateTime(DateUtils.parse(nest.getNeedDateTime(), DatePattern.NORM_DATETIME_FORMATTER).toLocalDateTime());
                qgApsWorkDetail.setPlanEndDateTime(DateUtils.parse(nest.getNeedDateTime(), DatePattern.NORM_DATETIME_FORMATTER).toLocalDateTime().plusHours(2));
                qgApsWorkDetail.setGroupCode(nest.getOptionId());
                qgApsWorkDetail.setAppendFlag(2);
                qgApsWorkDetail.setType(1);
                if (CollUtil.isNotEmpty(apsWorkDetails)) {
                    qgApsWorkDetail.setOrderId(apsWorkDetails.get(0).getOrderId());
                    qgApsWorkDetail.setApsOrderId(apsWorkDetails.get(0).getApsOrderId());
                }
                qgApsWorkDetail.setTotalWorkTime(2 * 60 * 60);
                qgApsWorkDetail.setWorkTime(2 * 60 * 60);
                apsWorkDetailList.add(qgApsWorkDetail);
//                String splitCode = getSplitCode(nest);
//                workChain.add(splitCode);
//                workChainGroupCode.add(nest.getOptionId());

                // 添加分捡工序
                Map<String, String> fjGroup = new HashMap<>();
                fjGroup.put("1-1_FHQG_00", "1-1_RGFJ_00");
                fjGroup.put("1-1_HYQG_00", "1-1_RGFJ_00");
                fjGroup.put("1-2_JGQG_00", "1-2_ZDFJ_00");
                fjGroup.put("1-3_JGQG_00", "1-3_ZDFJ_00");

                PlatePhase fjPhase = new PlatePhase();
                fjPhase.setPlateCode(plate.getMaterCode());
                fjPhase.setPhaseCode(WorkshopProp.FJ_PHASE_CODE);
                fjPhase.setPhaseName("分捡");
                fjPhase.setGroupCode(fjGroup.get(nest.getOptionId()));
                fjPhase.setPhaseSeq(platePhaseList.size() + 1);
                platePhaseList.add(fjPhase);

                ApsWorkDetail fjApsWorkDetail = new ApsWorkDetail();
                fjApsWorkDetail.setMaterNo(plate.getMaterCode());
                fjApsWorkDetail.setMaterName("钢板");
                fjApsWorkDetail.setPhaseId(fjPhase.getPhaseSeq());
                fjApsWorkDetail.setPhaseSeq(fjPhase.getPhaseSeq());
                fjApsWorkDetail.setPhaseCode(WorkshopProp.FJ_PHASE_CODE);
                fjApsWorkDetail.setPartCount(new BigDecimal(1));
                fjApsWorkDetail.setFinishCount(new BigDecimal(0));
                fjApsWorkDetail.setTotalCount(new BigDecimal(1));
                fjApsWorkDetail.setUniqueCode(plate.getMaterCode());
                fjApsWorkDetail.setStatus(2);
                fjApsWorkDetail.setPhaseName("分捡");
                fjApsWorkDetail.setPlanStartDateTime(DateUtils.parse(nest.getNeedDateTime(), DatePattern.NORM_DATETIME_FORMATTER).toLocalDateTime().plusHours(2));
                fjApsWorkDetail.setPlanEndDateTime(DateUtils.parse(nest.getNeedDateTime(), DatePattern.NORM_DATETIME_FORMATTER).toLocalDateTime().plusHours(5));
                fjApsWorkDetail.setGroupCode(fjGroup.get(nest.getOptionId()));
                fjApsWorkDetail.setAppendFlag(2);
                fjApsWorkDetail.setType(1);

                fjApsWorkDetail.setTotalWorkTime(3 * 60 * 60);
                fjApsWorkDetail.setWorkTime(3 * 60 * 60);
                if (CollUtil.isNotEmpty(apsWorkDetails)) {
                    fjApsWorkDetail.setOrderId(apsWorkDetails.get(0).getOrderId());
                    fjApsWorkDetail.setApsOrderId(apsWorkDetails.get(0).getApsOrderId());
                }
                apsWorkDetailList.add(fjApsWorkDetail);

                plate.setWorkChain(platePhaseList.stream().map(PlatePhase::getPhaseCode).collect(Collectors.joining("-")));
                return plate;
            }).collect(Collectors.toList());
            plateMapper.insertBatchSomeColumn(plateList);
            plateLlPhaseMap.forEach(this::makeLingliao);
            List<Plate> plateIdList = plateMapper.lambdaQuery().in(Plate::getMaterCode, plates.stream().map(SinoCamReceiveNestPlate::getStockListNo).collect(Collectors.toList())).list();
            Map<String, Plate> plateIdMap = plateIdList.stream().collect(Collectors.toMap(Plate::getMaterCode, e -> e));
            for (PlatePhase platePhase : platePhaseList) {
                platePhase.setPlateId(plateIdMap.get(platePhase.getPlateCode()).getId());
            }
            platePhaseMapper.insertBatchSomeColumn(platePhaseList);

            apsWorkDetailMapper.insertBatchSomeColumn(apsWorkDetailList);

            Map<String, Plate> collect = plateList.stream().collect(Collectors.toMap(Plate::getMaterCode, e -> e));

            // 领料表
            List<WmsPlatePick> platePickList = plates.stream()
                    .map(e -> {
                        WmsPlatePick pick = new WmsPlatePick();

                        pick.setPlateState(1);
                        pick.setNextWorkPlace(nest.getOptionId());
                        pick.setNestPlateId(e.getId());
                        pick.setAmount(1);// 数量
                        pick.setLength(e.getLength());
                        pick.setWidth(e.getWidth());
                        pick.setFastFlag(0);
                        pick.setReceiveDate(LocalDateTime.now());
                        pick.setPlannedStartTime(e.getPickDateTime());// 领料时间
                        pick.setType(1);
                        pick.setMaterialCode(e.getStockListNo());// 厚度
                        pick.setPlateMaterial(e.getTexture());
                        pick.setPlateThick(e.getNorm());// 厚度
                        pick.setMaterialId(e.getStockListNo());// 钢板编号（钢板物料号/材料编号？）
                        pick.setPlateUsage(e.getRate());// 利用率
                        pick.setNesting(vo.getPlate().get(0).getPngUrl());// 套料图号
                        pick.setMaterName(e.getMaterielName());// 钢板物料名称

                        Plate plate = collect.get(e.getStockListNo());// 钢板编号
                        pick.setPickingListNo(null);
                        pick.setPlanDate(null);
                        pick.setPackageSn(null);
                        pick.setWantDeliverDate(null);
                        pick.setStoragePlace(e.getPositionCode());
                        pick.setSeq(e.getSequence());
                        pick.setPickListItem(null);
                        pick.setPlateWeight(plate.getWeight());// 钢板重量
                        pick.setCloutWeight(null);
                        pick.setOutTime(null);
                        pick.setPlateNote(null);
                        pick.setPlateId(plate.getId());// 钢板ID
                        pick.setPlannedStartTime(LocalDate.parse(nest.getNeedDateTime(), DatePattern.NORM_DATETIME_FORMATTER).atStartOfDay());// 需求日期
                        pick.setNestId(nest.getNestId());
                        return pick;
                    })
                    .collect(Collectors.toList());
            wmsPlatePickMapper.insertBatchSomeColumn(platePickList);

            // 更新计划信息
            for (String nestPlanId : partMap.keySet()) {
                SinoCamPushPlan one = sinoCamPushPlanMapper.lambdaQuery().eq(SinoCamPushPlan::getNestPlanId, nestPlanId).one();
                if (one == null) {
                    throw SyExceptionUtils.e("推送计划不存在，nestPlanId:{}", nestPlanId);
                }
                int sum = partMap.get(nestPlanId).stream().mapToInt(SinoCamReceiveNestPart::getQuantity).sum();

                BigDecimal cha = one.getPlanAmount()
                        .subtract(one.getPlanFinishAmount())
                        .subtract(new BigDecimal(sum));

                if (cha.compareTo(new BigDecimal(0)) == 0) {
                    one.setConsumeStatus(2);
                    one.setPlanFinishAmount(new BigDecimal(sum).add(one.getPlanFinishAmount()));
                } else if (cha.compareTo(new BigDecimal(0)) > 0) {
                    one.setConsumeStatus(1);
                    one.setPlanFinishAmount(new BigDecimal(sum).add(one.getPlanFinishAmount()));
                } else {
                    throw SyExceptionUtils.e("套料异常，零件{}需要{}个，已套{}，待套{}，数量超了", one.getPartName(), one.getPlanAmount(), one.getPlanFinishAmount(), sum);
                }

                sinoCamPushPlanMapper.lambdaUpdate()
                        .eq(SinoCamPushPlan::getId, one.getId())
                        .set(SinoCamPushPlan::getStatus, one.getStatus())
                        .set(SinoCamPushPlan::getPlanFinishAmount, one.getPlanFinishAmount())
                        .set(SinoCamPushPlan::getModifyDateTime, LocalDateTime.now())
                        .update();

                NestSpacePart nestSpacePart = nestSpacePartMapper.lambdaQuery()
                        .eq(NestSpacePart::getPartPlanId, one.getId())
                        .eq(NestSpacePart::getSpaceId, nestSpace.getId())
                        .eq(NestSpacePart::getStatus, 2)
                        .one();
                if (nestSpacePart == null) {
                    throw SyExceptionUtils.e("绑定计划不存在，nestPlanId:{}", nestPlanId);
                }
                int sub = nestSpacePart.getTotalCount() - nestSpacePart.getFinishCount() - sum;
                if (sub == 0) {
                    nestSpacePart.setStatus(4);
                    nestSpacePart.setFinishCount(nestSpacePart.getFinishCount() + sum);
                } else if (sub > 0) {
                    nestSpacePart.setStatus(2);
                    nestSpacePart.setFinishCount(nestSpacePart.getFinishCount() + sum);
                } else {
                    throw SyExceptionUtils.e("套料异常，零件计划{},绑定ID{} 推送{}个，已套{}，待套{}，数量超了", nestSpacePart.getPartPlanId(), nestSpacePart.getId(), nestSpacePart.getTotalCount(), nestSpacePart.getFinishCount(), sum);
                }
                nestSpacePartMapper.lambdaUpdate()
                        .eq(NestSpacePart::getId, nestSpacePart.getId())
                        .set(NestSpacePart::getStatus, nestSpacePart.getStatus())
                        .set(NestSpacePart::getFinishCount, nestSpacePart.getFinishCount())
                        .set(NestSpacePart::getModifyDateTime, LocalDateTime.now())
                        .update();

            }

            nestSpacePlateMapper.lambdaUpdate()
                    .eq(NestSpacePlate::getSpaceId, nestSpace.getId())
                    .in(NestSpacePlate::getPlateCode, plates.stream().map(SinoCamReceiveNestPlate::getStockListNo).collect(Collectors.toList()))
                    .set(NestSpacePlate::getStatus, 4)
                    .set(NestSpacePlate::getCount, 1)
                    .set(NestSpacePlate::getModifyDateTime, LocalDateTime.now())
                    .update();

        }

    }

    public String getSplitCode(String optionId) {

        Map<String, String> params = new HashMap<>();
        params.put("1-1_FHQG_00", "HG");
        params.put("1-1_HYQG_00", "HG");
        params.put("1-2_JGQG_00", "JG");
        params.put("1-3_JGQG_00", "JG");

        String groupCode = params.get(optionId);
        if (groupCode == null) {
            throw SyExceptionUtils.e("未知的切割工作组：{}", optionId);
        }

        return groupCode;
    }

    public void makeLingliao(String materCode, PlatePhase llPhase) {
        Plate plate = plateMapper.lambdaQuery().eq(Plate::getMaterCode, materCode).one();
        SinoCamReceiveNestPlate nestPlate = sinoCamReceiveNestPlateMapper.lambdaQuery().eq(SinoCamReceiveNestPlate::getStockListNo, materCode).one();
        List<SinoCamReceiveNestPart> nestParts = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getPlateCode, materCode).list();
        List<ApsWorkDetail> apsWorkDetails = apsWorkDetailMapper.selectBatchIds(nestParts.stream().map(SinoCamReceiveNestPart::getNestPlanId).distinct().collect(Collectors.toList()));
        List<Integer> orderIds = apsWorkDetails.stream().map(ApsWorkDetail::getOrderId).distinct().collect(Collectors.toList());
        WorkDetailTask plateTask = new WorkDetailTask();
        plateTask.setMaterCode(plate.getMaterCode());
        plateTask.setMaterName(plate.getMaterName());
        plateTask.setPhaseCode(llPhase.getPhaseCode());
        plateTask.setPhaseName(llPhase.getPhaseName());
        plateTask.setGroupCode(llPhase.getGroupCode());
        plateTask.setStationCode(WorkshopProp.LL_STATION_FIRST);
        plateTask.setStatus(2);
        plateTask.setType(1);
        plateTask.setPlanStartDateTime(plate.getNestDateTime());
        plateTask.setPlanEndDateTime(plateTask.getPlanStartDateTime().plusHours(2));
        if (!CollectionUtils.isEmpty(orderIds)) {
            List<Order> orders = orderMapper.selectBatchIds(orderIds);
            plateTask.setOrderCode(orders.stream().map(Order::getConstructNo).distinct().collect(Collectors.joining(",")));
        }
        plateTask.setNorm(plate.getNorm());
        plateTask.setTexture(plate.getTexture());
        plateTask.setWeight(plate.getNestWeight());
        plateTask.setNestPlateId(nestPlate.getId());
        plateTask.setNestId(plate.getNestId());

        plateTask.setPlmid(plate.getMaterCode());
        plateTask.setTotalCount(1);
        plateTask.setNextGroupCode(WorkshopProp.YC_GROUP);
        plateTask.setNextPhaseCode(WorkshopProp.YC_PHASE_CODE);
        plateTask.setPlateCode(plate.getMaterCode());
        plateTask.setLength(plate.getLength());
        plateTask.setWidth(plate.getWidth());
        plateTask.setThickness(BigDecimal.valueOf(Integer.parseInt(plate.getNorm())));
        workDetailTaskMapper.insert(plateTask);
    }

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public NestReceiveReqVo nestReceiveNew(String body) {

        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, LantekReceiveNestReqVo.class);
        List<LantekReceiveNestReqVo> reqVos = objectMapper.readValue(body, javaType);
        LantekReceiveNestReqVo reqVo = reqVos.get(0);

        LantekReceiveNestNestReqVo reNest = reqVo.getNest();
        List<LantekReceiveNestPartReqVo> rePart = reqVo.getPart();
        List<LantekReceiveNestPlateReqVo> rePlate = reqVo.getPlate();
        List<LantekReceiveNestExcessReqVo> reExcess = reqVo.getExcess();
        List<LantekReceiveNestMoveReqVo> reMove = reqVo.getMove();

        NestReceiveReqVo resVo = new NestReceiveReqVo();
        NestReceiveNestReqVo nest = new NestReceiveNestReqVo();
        List<NestReceivePartReqVo> part = new ArrayList<>();
        List<NestReceivePlateReqVo> plate = new ArrayList<>();
        List<NestReceiveExcessReqVo> excess = new ArrayList<>();
        List<NestReceiveMoveReqVo> move = new ArrayList<>();

        // 套料信息
        nest = MkBeanUtils.copyProperties(reNest, NestReceiveNestReqVo.class);
        int type = isPre() ? 1 : 2;
        nest.setType(reNest.getPlanType() != null ? reNest.getPlanType() : type);
        nest.setSource(getSource());
        nest.setNestCode(reNest.getNestId());
        nest.setFactoryCode("170");
        nest.setNestDateTime(reNest.getNestDateTime());
        nest.setNeedDateTime(reNest.getNeedDateTime());
        nest.setNestUserCode(reNest.getNester());
        nest.setSplitGroupCode(reNest.getOptionId());
        nest.setBookSheet(reNest.getBookSheet());
        nest.setNestDxf(reNest.getDxfUrl());
        nest.setReportPdf(reNest.getReportPdfUrl());
        nest.setCuttingProgram(reNest.getCuttingProgramUrl());
        nest.setChangeDateTime(reNest.getChangeDateTime());
        nest.setChanger(reNest.getChanger());
        nest.setJobRef(reNest.getJobRef());

        // 钢板信息
        if (CollUtil.isEmpty(rePlate)) {
            throw SyExceptionUtils.e("缺少钢板信息：{}", reNest.getNestId());
        }
        plate = rePlate.stream().map(e -> {
            NestReceivePlateReqVo vo = new NestReceivePlateReqVo();
            vo.setRate(reNest.getRate());
            vo.setPlatePng(e.getPngUrl());
            vo.setPlatePdf(e.getPdfUrl());
            vo.setPlateCode(e.getPlateCode());
            vo.setTexture(e.getTexture());
            vo.setThickness(e.getThickness());
            vo.setWidth(e.getWidth());
            vo.setLength(e.getLength());
            vo.setPositionCode(e.getPositionCode());
            vo.setSequence(e.getSequence());
            vo.setHeatCode(e.getHeatId());
            vo.setSideLength(reNest.getSideLength());
            vo.setNestArea(e.getNestArea());
            vo.setNestCode(reNest.getNestId());
            return vo;
        }).collect(Collectors.toList());

        // 零件信息
        if (CollUtil.isEmpty(rePart)) {
            throw SyExceptionUtils.e("缺少零件信息：{}", reNest.getNestId());
        }
        part = rePart.stream().map(e -> {
            NestReceivePartReqVo vo = new NestReceivePartReqVo();
            vo.setPlanId(e.getPartPlanId());
            if (e.getPartId().contains("#")) {
                String partId = e.getPartId();
                String[] split = partId.split("#");
                vo.setPlmId(split[0]);
            } else {
                vo.setPlmId(e.getPartId());
            }
            vo.setMaterName(e.getPartName());
            vo.setUniCode(e.getPartId());
            vo.setTotalCount(e.getQuantity());
            vo.setNetWeight(e.getNetWeight());
            vo.setWidth(e.getWidth());
            vo.setLength(e.getLength());
            vo.setThickness(e.getThickness());
            vo.setArea(e.getArea());
            vo.setRectangleArea(e.getRectangleArea());
            vo.setPlateCode(e.getPlateCode());
            vo.setPartPng(e.getPngUrl());
            vo.setPartPdf(e.getPdfUrl());
            vo.setOrderId(e.getOrderId());
            vo.setNestCode(reNest.getNestId());
            return vo;
        }).collect(Collectors.toList());

        // 余料信息
        if (CollUtil.isNotEmpty(reExcess)) {
            excess = reExcess.stream().map(e -> {
                NestReceiveExcessReqVo vo = new NestReceiveExcessReqVo();
                vo.setExcessCode(e.getExcessCode());
                vo.setPlateCode(e.getPlateCode());
                vo.setTexture(e.getTexture());
                vo.setThickness(e.getThickness());
                vo.setLength(e.getLength());
                vo.setWidth(e.getWidth());
                vo.setWeight(e.getWeight());
                vo.setExcessPng(e.getPngUrl());
                vo.setNestCode(reNest.getNestId());
                return vo;
            }).collect(Collectors.toList());
        }

        // 走刀切割信息
        move = reMove.stream().map(e -> {
            NestReceiveMoveReqVo vo = new NestReceiveMoveReqVo();
            vo.setMoveType(e.getMoveType());
            vo.setCutLength(e.getCutLength());
            vo.setMoveTime(e.getMoveTime());
            vo.setHoleCount(e.getHoleCount());
            vo.setHoleTime(e.getHoleTime());
            vo.setTotalHoleTime(e.getTotalHoleTime());
            vo.setCutRate(e.getCutRate());
            vo.setTotalCutTime(e.getTotalCutTime());
            vo.setNestCode(reNest.getNestId());
            return vo;
        }).collect(Collectors.toList());

        resVo.setNest(nest);
        resVo.setPlate(plate);
        resVo.setPart(part);
        resVo.setExcess(excess);
        resVo.setMove(move);

        return resVo;

    }

}
